import React from "react";
import { useStyles, usePopoverStyles } from "./style";
import classnames from "classnames";
import { AttackPhaseProps, AttackPhaseType } from "./type";
import {
  BoldArrow,
  Control,
  ControlSelected,
  Delivery,
  DeliverySelected,
  Goal,
  GoalSelected,
  Intrusion,
  IntrusionBroken,
  IntrusionSelected,
  IntrusionUnbroken,
  Lateral,
  LateralSelected,
  Recon,
  ReconSelected,
} from "@ct0/icons";
import { BROKEN_PHASES } from "./index";
import { Popover } from "../Tooltip";

interface ColProps {
  classname?: string;
  children?: React.ReactNode;
}

interface ArrowItemProps {
  classname?: string;
  isBroken?: boolean;
}

interface ItemProps
  extends Pick<AttackPhaseProps, "popoverVisible" | "onPopoverJump"> {
  name: string;
  count: number;
  type:
    | AttackPhaseType.Control
    | AttackPhaseType.Goal
    | AttackPhaseType.Recon
    | AttackPhaseType.Delivery
    | AttackPhaseType.Lateral;
  onClick: (type: AttackPhaseType) => void;
  phases: AttackPhaseType[];
}

interface IntrusionItemProps extends Omit<ItemProps, "type"> {
  onClick: () => void;
}

function ItemCol({ classname, children }: ColProps) {
  const classes = useStyles();
  return <div className={classnames(classes.col, classname)}>{children}</div>;
}

function ArrowItem({ classname, isBroken }: ArrowItemProps) {
  const classes = useStyles();
  return (
    <div className={classnames(classes.item, classname)}>
      <div className={classes.iconContainer}>
        {isBroken ? (
          <span className={classes.arrowBroken}>
            <BoldArrow />
          </span>
        ) : (
          <span className={classes.arrowUnBroken}>
            <BoldArrow />
          </span>
        )}
      </div>
    </div>
  );
}

function IntrusionItem({
  phases,
  name,
  count,
  onClick: handleClick,
  popoverVisible,
  onPopoverJump,
}: IntrusionItemProps) {
  const classes = useStyles();
  const [isNotBroken, isBroken] = [
    phases?.includes(AttackPhaseType.Intrusion_Unbroken),
    phases?.includes(AttackPhaseType.Intrusion_Broken),
  ];
  const getIconAndClass = () => {
    if (isNotBroken && isBroken) {
      return [<IntrusionSelected />, classes.selectedUnbroken];
    }
    if (!isNotBroken && !isBroken) {
      return [<Intrusion />, classes.unSelected];
    }
    if (isBroken && !isNotBroken) {
      return [<IntrusionBroken />, classes.selectedBroken];
    }
    if (isNotBroken && !isBroken) {
      return [<IntrusionUnbroken />, classes.selectedUnbroken];
    }
    return [];
  };

  const [icon, selectedClass] = getIconAndClass();
  return (
    <div className={classnames(classes.item, selectedClass)}>
      {popoverVisible ? (
        <PopoverContext
          name={name}
          count={count}
          onPopoverJump={onPopoverJump}
          type={[
            AttackPhaseType.Intrusion_Unbroken,
            AttackPhaseType.Intrusion_Broken,
          ]}
        >
          <div className={classes.iconContainer}>
            <span onClick={() => handleClick?.()} className={classes.stepIcon}>
              {icon}
            </span>
          </div>
        </PopoverContext>
      ) : (
        <div className={classes.iconContainer}>
          <span onClick={() => handleClick?.()} className={classes.stepIcon}>
            {icon}
          </span>
        </div>
      )}
      <span className={classes.itemName}>{name}</span>
      {count !== undefined && <span className={classes.count}>({count})</span>}
    </div>
  );
}

const IconComponent = {
  [AttackPhaseType.Recon]: [<Recon />, <ReconSelected />],
  [AttackPhaseType.Delivery]: [<Delivery />, <DeliverySelected />],
  [AttackPhaseType.Control]: [<Control />, <ControlSelected />],
  [AttackPhaseType.Lateral]: [<Lateral />, <LateralSelected />],
  [AttackPhaseType.Goal]: [<Goal />, <GoalSelected />],
};

function Item({
  phases,
  name,
  count,
  type,
  onClick: handleClick,
  popoverVisible,
  onPopoverJump,
}: ItemProps) {
  const classes = useStyles();
  const isSelected = type && phases?.includes(type);
  const selectedClass = !isSelected
    ? classes.unSelected
    : BROKEN_PHASES.includes(type)
    ? classes.selectedBroken
    : classes.selectedUnbroken;
  const [unchecked, checked] = type ? IconComponent?.[type] : [];

  return (
    <div className={classnames(classes.item, selectedClass)}>
      {popoverVisible ? (
        <PopoverContext
          name={name}
          type={[type]}
          count={count}
          onPopoverJump={onPopoverJump}
        >
          <div className={classes.iconContainer}>
            <span
              onClick={() => type && handleClick?.(type)}
              className={classes.stepIcon}
            >
              {isSelected ? checked : unchecked}
            </span>
          </div>
        </PopoverContext>
      ) : (
        <div className={classes.iconContainer}>
          <span
            onClick={() => type && handleClick?.(type)}
            className={classes.stepIcon}
          >
            {isSelected ? checked : unchecked}
          </span>
        </div>
      )}
      <span className={classes.itemName}>{name}</span>
      {count !== undefined && <span className={classes.count}>({count})</span>}
    </div>
  );
}

interface PopoverOverlayProps
  extends Pick<ItemProps, "name" | "count" | "onPopoverJump"> {
  type: AttackPhaseType[];
  children: React.ReactNode;
}

function PopoverContext({
  type,
  name,
  count,
  onPopoverJump,
  children,
}: PopoverOverlayProps) {
  const onClick = () => onPopoverJump?.(type);
  const classes = usePopoverStyles();
  return (
    <Popover
      placement="top"
      overlay={
        <div className={classes.popoverContainer}>
          <div className={classes.item}>
            <span className={classes.label}>攻击阶段</span>
            <span className={classes.value}>{name}</span>
          </div>
          <div className={classes.item}>
            <span className={classes.label}>告警统计</span>
            <span
              className={classnames(classes.value, {
                [classes.highlight]: !!onPopoverJump,
              })}
              onClick={onClick}
            >
              {count}
            </span>
          </div>
        </div>
      }
    >
      <span>{children}</span>
    </Popover>
  );
}
export { ItemCol, ArrowItem, Item, IntrusionItem };
